package com.yyplatform.admin.infra.web.interceptor;

import java.util.Date;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.json.JSONObject;
import org.springframework.web.servlet.HandlerInterceptor;

import com.yyplatform.admin.infra.web.shiro.CurrentUser;
import com.yyplatform.admin.infra.web.shiro.CurrentUserHolder;
import com.yyplatform.admin.infra.utils.RequestUtils;
import com.yyplatform.admin.platform.log.entity.SysOperationLogEntity;
import com.yyplatform.admin.platform.log.repository.SysOperationLogRepository;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;

/**
 * @author sleepforests@163.com
 * <p>
 * Created on 2024/9/20 20:42
 */
@Slf4j
public class OperationLogInterceptor implements HandlerInterceptor {

    private static final String OP_LOG_KEY = "_attr_op_log";
    private static final String OP_LOG_COST_KEY = "_attr_op_log_cost";
    private static final String FORM_CONTENT_TYPE = "multipart/form-data";

    private SysOperationLogRepository sysOperationLogRepository;

    public OperationLogInterceptor(SysOperationLogRepository logRepository) {
        this.sysOperationLogRepository = logRepository;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        SysOperationLogEntity logEntity = new SysOperationLogEntity();

        CurrentUser currentUser = CurrentUserHolder.getCurrentUser();
        if (currentUser != null && currentUser.getId() != null && currentUser.getId() > 0) {
            logEntity.setUsername(currentUser.getUsername());
            logEntity.setUserId(currentUser.getId());
            logEntity.setRealName(currentUser.getRealName());
        } else {
            logEntity.setUsername("");
            logEntity.setUserId(0L);
            logEntity.setRealName("");
        }

        logEntity.setBusinessType("");
        logEntity.setBusinessName("");
        logEntity.setJavaMethod("");

        logEntity.setUri(request.getRequestURI());
        logEntity.setMethod(request.getMethod());
        logEntity.setRequestTime(new Date());


        logEntity.setUserAgent(RequestUtils.getUserAgent(request));
        logEntity.setIp(RequestUtils.getIp(request));
        logEntity.setLocation(RequestUtils.getLocation(request));
        logEntity.setBrowser(RequestUtils.getBrowser(request));
        logEntity.setOs(RequestUtils.getOs(request));
        logEntity.setRequestTime(new Date());


        // todo
        logEntity.setParamJson("");
        logEntity.setResultJson("");

        String method = request.getMethod();
        String contentType = request.getContentType();

        if (StringUtils.equals(method, "GET")) {
            Map<String, String[]> params = request.getParameterMap();
            JSONObject jsonObject = new JSONObject(params);
            logEntity.setParamJson(jsonObject.toString());

        } else if (StringUtils.equals(method, "POST")) {
            if (contentType != null) {
                if (contentType.contains(FORM_CONTENT_TYPE)) {
                    Map<String, String[]> params = request.getParameterMap();
                    JSONObject jsonObject = new JSONObject(params);
                    logEntity.setParamJson(jsonObject.toString());
                }

                if (contentType.contains("application/json")) {
                    //                    ContentCachingRequestWrapper wrapper = (ContentCachingRequestWrapper) request;
                    //                    String jsonBody = new String(wrapper.getContentAsByteArray(), "UTF-8");
                    //                    logEntity.setParamJson(jsonBody);
                }
            } else {
                Map<String, String[]> params = request.getParameterMap();
                JSONObject jsonObject = new JSONObject(params);
                logEntity.setParamJson(jsonObject.toString());
            }
        }


        logEntity.setErrorCode(0);
        logEntity.setErrorMsg("OK");

        request.setAttribute(OP_LOG_COST_KEY, System.currentTimeMillis());
        request.setAttribute(OP_LOG_KEY, logEntity);

        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        SysOperationLogEntity logEntity = (SysOperationLogEntity) request.getAttribute(OP_LOG_KEY);
        long t1 = (Long) request.getAttribute(OP_LOG_COST_KEY);
        long t2 = System.currentTimeMillis();

        logEntity.setCost((int) (t2 - t1));

        int status = response.getStatus();


        try {
            //            log.debug("begin to insert into operation log, {}", logEntity);
            sysOperationLogRepository.save(logEntity);
        } catch (Exception e) {
            log.error("save operation log error", e);
        }

        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}
